package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;
    @Autowired
    private AlbumInfoService albumInfoService;
    @Autowired
    private VodService vodService;
    @Autowired
    private TrackStatMapper trackStatMapper;
    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        //保存3张表track_info track_stat album_info
        TrackInfo trackInfo = new TrackInfo();
        //获取专辑对象
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
        //	赋值
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //用户id
        trackInfo.setUserId(userId);
        //声音序号
        trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
        //  声音相关的数据集; 可以调用api接口; mediaFileId 查询！
        TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
        trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
        trackInfo.setMediaType(trackMediaInfoVo.getType());
        trackInfo.setMediaSize(trackMediaInfoVo.getSize());
        trackInfoMapper.insert(trackInfo);
        //2.track_stat
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);
        //3.album_info

        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
        albumInfoMapper.updateById(albumInfo);
    }

    @Override
    public IPage<TrackListVo> findUserTrackPage(Page<Object> trackListVoPage, TrackInfoQuery trackInfoQuery) {

        return trackInfoMapper.selectUserTrackPage(trackListVoPage, trackInfoQuery);

    }

    private void saveTrackStat(Long trackId, String statPlay) {
        TrackStat trackStat = new TrackStat();
        trackStat.setTrackId(trackId);
        trackStat.setStatType(statPlay);
        trackStat.setStatNum(new Random().nextInt(1000000));
        //保存数据
        trackStatMapper.insert(trackStat);
    }

    /**
     * 根据id删除声音
     *
     * @param trackId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeTrackInfo(Long trackId) {
        //根据 trackid 获取专辑对象
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        try {
            //删除三张表的数据
            //track_info; 维护order_num 序号问题！
            trackInfoMapper.deleteById(trackId);
            //  更新order_num 序号; update track_info set order_num = order_num - 1 where album_id = 1 and order_num > 51
            trackInfoMapper.updateOrderNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());
            //track_stat
            trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));
            //  album_info; 修改专辑包含声音总数;
            AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
            albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
            albumInfoMapper.updateById(albumInfo);
            //删除云点播数据
            vodService.removeMedia(trackInfo.getMediaFileId());
            return true;
            //  删除成功;
        } catch (Exception e) {
            //  删除失败，记录日志信息。
            log.error(e.getMessage(), e);
        }
        //  表示删除失败！
        return false;
    }

    /**
     * 修改声音数据
     *
     * @param trackInfoVo
     * @param trackId
     */
    @Override
    public void updateTrackInfo(TrackInfoVo trackInfoVo, Long trackId) {
        //判断是否修改音频
        //先获取旧的声音表
        TrackInfo trackInfo = this.getById(trackId);
        //获取旧的流媒体id
        String originMediaFileId = trackInfo.getMediaFileId();
        //把数据拷贝过去
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //比较流媒体id 判断是否修改音频
        if (!trackInfoVo.getMediaFileId().equals(originMediaFileId)) {
            //获取流媒体数据
            TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfo.getMediaFileId());
            //  将流媒体最新数据进行赋值;
            trackInfo.setMediaSize(mediaInfo.getSize());
            trackInfo.setMediaDuration(mediaInfo.getDuration());
            trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
            trackInfo.setMediaType(mediaInfo.getType());
            vodService.removeMedia(originMediaFileId);
        }
        //更新数据
        trackInfoMapper.updateById(trackInfo);


    }

    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> albumTrackListVoPage, Long albumId, Long userId) {
        //1.根据专辑id查询声音列表track_info  track_stat
        IPage<AlbumTrackListVo> iPage = trackInfoMapper.selectAlbumTrackPage(albumTrackListVoPage, albumId);
        //2.根据用户id判断用户信息
        // 用户未登录： 0101-免费、0102-vip免费、0103-付费 -- 除去免费的专辑之外都应该有试听集数(不需要付费，反之)
        // 用户登录：  专辑类型是vip免费 - 用户不是vip或是vip但是已经过期了，需要显示付费！ 付费：必须得给钱!
        AlbumInfo albumInfo = this.albumInfoMapper.selectById(albumId);
        //判断是否登录
        if (null == userId) {
            //查看专辑是否付费
            if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
                //是付费类型 vip 免费 付费
//                List<AlbumTrackListVo> records = iPage.getRecords();
//                for (AlbumTrackListVo record : records) {
//                    if (record.getOrderNum() > albumInfo.getTracksForFree()) {
//                        record.setIsShowPaidMark(true);
//                    }
//                }
                //除试听声音给剩余声音加锁 收费
                iPage.getRecords().stream().filter(albumTrackListVo ->
                                albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
                        .forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));

                return iPage;
            }
        } else {
            //  3.  设置布尔类型变量判断是否需要付费： true: 付费，false: 免费    true: 需要判断当前用户是否购买了专辑或购买声音！
            //  声明一个变量判断当前是否需要付费;
            boolean isNeedPaid = false;
            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())) {
                //vip 免费  不是vip 或者vip 过期需要付费
                //远程调用获取用户信息
                Result<UserInfoVo> userInfo = userInfoFeignClient.getUserInfo(userId);
                Assert.notNull(userInfo, "查询用户信息失败");
                UserInfoVo userInfoVo = userInfo.getData();
                Assert.notNull(userInfoVo, "查询用户信息失败");
                if (userInfoVo.getIsVip() == 0 || userInfoVo.getIsVip() == 1 && userInfoVo.getVipExpireTime().before(new Date())) {
                    isNeedPaid = true;
                }
            }else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
                isNeedPaid = true;
            }
            //统一处理付费
            if (isNeedPaid) {
                //获取需要购买的专辑 声音列表id
                List<AlbumTrackListVo> albumTrackListVoList = iPage.getRecords().stream()
                        .filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
                        .collect(Collectors.toList());
                List<Long> trackIdNeedPaidList = albumTrackListVoList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
                //远程调用
                //  map.put(key,value) key=trackId value=1或0 1：表示当前声音已购买,0:表示未购买！
                Result<Map<Long, Integer>> mapResult = userInfoFeignClient.userIsPaidTrack(albumId, trackIdNeedPaidList);
                Assert.notNull(mapResult, "查询用户信息失败");
                Map<Long, Integer> map = mapResult.getData();
                Assert.notNull(map, "查询用户信息失败");
                for (AlbumTrackListVo albumTrackListVo : albumTrackListVoList) {
                    albumTrackListVo.setIsShowPaidMark(map.get(albumTrackListVo.getTrackId()) == 0);
                }



        }
    }

        return null;
}

@Override
public void updateTrackStat(TrackStatMqVo trackStatMqVo) {
    //修改声音与专辑播放量
    trackInfoMapper.updateTrackStat(trackStatMqVo.getTrackId(), trackStatMqVo.getStatType());
    //修改专辑播放量 判断是不是更改的是播放量
    if (trackStatMqVo.getStatType().equals(SystemConstant.TRACK_STAT_PLAY)) {
        albumInfoMapper.updateAlbumStat(trackStatMqVo.getAlbumId(), SystemConstant.ALBUM_STAT_PLAY);
    } else if (trackStatMqVo.getStatType().equals(SystemConstant.TRACK_STAT_COLLECT)) {
        //修改收藏量  剩下几个

    }
}

@Override
public List<Map<String, Object>> findUserPaidTrackList(Long trackId) {
    //根据id获取当前声音列表
    TrackInfo trackInfo = this.trackInfoMapper.selectById(trackId);
    //获取专辑对象 获取声音价格
    AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
    //1.从当前声音 trackId 开始到结束一共还有多少集? 除去用户已购买的声音列表;
    //根据专辑Id 获取到用户已购买的声音Id集合
    Result<List<Long>> trackIdListResult = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
    Assert.notNull(trackIdListResult, "查询用户已购买的声音Id集合失败");
    List<Long> trackIdList = trackIdListResult.getData();
    //用户可能会没有购买专辑
    //查询当前专辑对应的所有声音列表;
    LambdaQueryWrapper<TrackInfo> Wrapper = new LambdaQueryWrapper<>();
    Wrapper.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId()).gt(TrackInfo::getId, trackId);
    //查询所有列表集合
    List<TrackInfo> trackInfoList = trackInfoMapper.selectList(Wrapper);
    //只需要获取声音id
    List<Long> trackIdPaidList = trackInfoList.stream().map(TrackInfo::getId).collect(Collectors.toList());
    //进行比较判断 获取差集 需要购买的声音列表
    List<Long> trackIdNeedPaidList = trackIdPaidList.stream().filter(tid -> !trackIdList.contains(tid)).collect(Collectors.toList());

    //2.声音的价格 有单集购买页可以多集够买也可以整专辑购买
    List<Map<String, Object>> list = new ArrayList<>();
    //判断
    if (trackIdNeedPaidList.size() >= 0) {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "本集");
        map.put("price", albumInfo.getPrice());
        map.put("trackCount", 0);
        list.add(map);
    }
    if (trackIdNeedPaidList.size() > 0 && trackIdNeedPaidList.size() <= 10) {
        Map<String, Object> map = new HashMap<>();
        int size = trackIdNeedPaidList.size();
        map.put("name", "后" + size + "集");
        map.put("price", albumInfo.getPrice().multiply(BigDecimal.valueOf(size)));
        map.put("trackCount", size);
        //添加到
        list.add(map);
    }
    //   后10集
    if (trackIdNeedPaidList.size() > 10) {
        //  构建本集之后的声音;
        Map<String, Object> map = new HashMap<>();
        map.put("name", "后10集");
        map.put("price", albumInfo.getPrice().multiply(new BigDecimal("10")));
        map.put("trackCount", 10);
        //  将这个map 添加到集合;
        list.add(map);
    }
    //  后15集;
    if (trackIdNeedPaidList.size() > 10 && trackIdNeedPaidList.size() <= 20) {
        //  构建本集之后的声音;
        Map<String, Object> map = new HashMap<>();
        int size = trackIdNeedPaidList.size();
        map.put("name", "后" + size + "集");
        map.put("price", albumInfo.getPrice().multiply(BigDecimal.valueOf(size)));
        map.put("trackCount", size);
        //  将这个map 添加到集合;
        list.add(map);
    }
    //   后20集
    if (trackIdNeedPaidList.size() > 20) {
        //  构建本集之后的声音;
        Map<String, Object> map = new HashMap<>();
        map.put("name", "后20集");
        map.put("price", albumInfo.getPrice().multiply(new BigDecimal("20")));
        map.put("trackCount", 20);
        //  将这个map 添加到集合;
        list.add(map);
    }
    //  后28集;
    if (trackIdNeedPaidList.size() > 20 && trackIdNeedPaidList.size() <= 30) {
        //  构建本集之后的声音;
        Map<String, Object> map = new HashMap<>();
        int size = trackIdNeedPaidList.size();
        map.put("name", "后" + size + "集");
        map.put("price", albumInfo.getPrice().multiply(BigDecimal.valueOf(size)));
        map.put("trackCount", size);
        //  将这个map 添加到集合;
        list.add(map);
    }
    //   后30集
    if (trackIdNeedPaidList.size() > 30) {
        //  构建本集之后的声音;
        Map<String, Object> map = new HashMap<>();
        map.put("name", "后30集");
        map.put("price", albumInfo.getPrice().multiply(new BigDecimal("30")));
        map.put("trackCount", 30);
        //  将这个map 添加到集合;
        list.add(map);
    }
    //  返回数据
    return list;
}

@Override
public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount) {
    //创建声音集合
    List<TrackInfo> list = new ArrayList<>();
    //获取当前声音
    TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
    //  1.  从当前声音开始，向后数多少集; 先获取到购买的声音Id列表;
    //远程调用通过 专辑id 查询用户已购买的声音Id列表;
    Result<List<Long>> userPaidTrackList = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
    Assert.notNull(userPaidTrackList, "查询用户已购买声音Id列表失败");
    List<Long> paidTrackIdList = userPaidTrackList.getData();
    //用户可能未购买声音
    //判断用户是否购买的是本集
    if (trackCount > 0) {
        //查询条件
        LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId()).gt(TrackInfo::getId, trackId);
        if (!CollectionUtils.isEmpty(paidTrackIdList)) {
            wrapper.notIn(TrackInfo::getId, paidTrackIdList);
        }
        //限制查询条数
        wrapper.last("limit " + trackCount);
        list = trackInfoMapper.selectList(wrapper);
    } else {
        //购买本集
        list.add(trackInfo);
    }
    return list;
}

}
